package com.greensam.pixelengine.manager.auth;

import com.greensam.pixelengine.exception.BusinessException;
import com.greensam.pixelengine.pojo.emuns.ErrorCodeEnum;
import com.greensam.pixelengine.pojo.emuns.RoleEnum;
import com.greensam.pixelengine.pojo.emuns.StatusEnum;
import com.greensam.pixelengine.pojo.emuns.TeamSpaceRoleEnum;
import com.greensam.pixelengine.pojo.entity.PermissionPo;
import com.greensam.pixelengine.pojo.entity.RolePermissionPo;
import com.greensam.pixelengine.pojo.entity.RolePo;
import com.greensam.pixelengine.service.PermissionDataService;
import com.greensam.pixelengine.service.RoleDataService;
import com.greensam.pixelengine.service.RolePermissionDataService;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 初始化角色权限
 *
 * @author Ma Chengrui
 * @since 2025/9/29 10:28
 */
@Component
@RequiredArgsConstructor
public class RolePermissionInitializer implements CommandLineRunner {

    private final RoleDataService roleDataService;
    private final PermissionDataService permissionDataService;
    private final RolePermissionDataService rolePermissionDataService;
    private final SpaceUserAuthManager spaceUserAuthManager;

    @Override
    public void run(String... args) {
        // 初始化权限
        initPermission();
        // 初始化系统角色
        initSystemRole();
        // 初始化团队空间角色
        initTeamSpaceRole();
        // 初始化角色权限关系
        initRolePermission();
    }

    private void initPermission() {
        spaceUserAuthManager.listAllPermissions().forEach(permissionDef -> {
            PermissionPo permissionPo = permissionDataService.getPermissionByCode(permissionDef.getKey())
                    .orElse(new PermissionPo());
            permissionPo.setCreateBy(1L);
            permissionPo.setUpdateBy(1L);
            permissionPo.setCode(permissionDef.getKey());
            permissionPo.setName(permissionDef.getName());
            permissionPo.setDescription(permissionDef.getDescription());
            permissionDataService.save(permissionPo);
        });
    }

    /**
     * 初始化系统角色
     */
    private void initSystemRole() {
        Arrays.stream(RoleEnum.values()).forEach(roleEnum -> {
            RolePo rolePo = roleDataService.getRolePoByCode(roleEnum.getCode())
                    .orElse(new RolePo());
            rolePo.setCreateBy(1L);
            rolePo.setUpdateBy(1L);
            rolePo.setCode(roleEnum.getCode());
            rolePo.setName(roleEnum.getName());
            rolePo.setDescription(roleEnum.getDescription());
            rolePo.setSort(0);
            rolePo.setStatus(StatusEnum.Approved);
            roleDataService.save(rolePo);
        });
    }

    /**
     * 初始化团队空间角色
     */
    private void initTeamSpaceRole() {
        Arrays.stream(TeamSpaceRoleEnum.values()).forEach(teamSpaceRoleEnum -> {
            RolePo rolePo = roleDataService.getRolePoByCode(teamSpaceRoleEnum.getCode())
                    .orElse(new RolePo());
            rolePo.setCreateBy(1L);
            rolePo.setUpdateBy(1L);
            rolePo.setCode(teamSpaceRoleEnum.getCode());
            rolePo.setName(teamSpaceRoleEnum.getName());
            rolePo.setDescription(teamSpaceRoleEnum.getDescription());
            rolePo.setSort(0);
            rolePo.setStatus(StatusEnum.Approved);
            roleDataService.save(rolePo);
        });
    }

    /**
     * 初始化角色对应权限
     */
    private void initRolePermission() {
        spaceUserAuthManager.listAllRoles().forEach(roleDef -> {
            RolePo rolePo = roleDataService.getRolePoByCode(roleDef.getKey())
                    .orElseThrow(() -> new BusinessException(ErrorCodeEnum.RoleNotExist, ("角色未初始化：" + roleDef.getKey())));

            // 查询数据库中该角色已有的权限
            List<RolePermissionPo> rolePermissionPos = rolePermissionDataService.listRolePermissionByRoleId(rolePo.getId());
            Set<Long> permissionIds = rolePermissionPos.stream()
                    .map(RolePermissionPo::getPermissionId)
                    .collect(Collectors.toSet());
            Map<Long, RolePermissionPo> dbPermissionMap = rolePermissionPos.stream()
                    .collect(Collectors.toMap(RolePermissionPo::getPermissionId, Function.identity()));

            // 数据库中的权限code
            Set<String> dbPermissionCodes = permissionDataService.listPermissionByIds(permissionIds).stream()
                    .map(PermissionPo::getCode)
                    .collect(Collectors.toSet());
            // 配置文件中的权限code
            List<String> defPermissionCodes = roleDef.getPermissions();

            // 配置文件有、数据库没有 → 新增权限
            Set<String> missingPermissionCodes = defPermissionCodes.stream()
                    .filter(code -> !dbPermissionCodes.contains(code))
                    .collect(Collectors.toSet());
            if (!missingPermissionCodes.isEmpty()) {
                List<PermissionPo> permissionList = permissionDataService.listPermissionByCodes(missingPermissionCodes);
                permissionList.forEach(permissionPo -> {
                    RolePermissionPo rolePermissionPo = new RolePermissionPo();
                    rolePermissionPo.setCreateBy(1L);
                    rolePermissionPo.setUpdateBy(1L);
                    rolePermissionPo.setRoleId(rolePo.getId());
                    rolePermissionPo.setPermissionId(permissionPo.getId());
                    rolePermissionDataService.save(rolePermissionPo);
                });
            }

            // 配置文件没有、数据库有 → 删除权限
            Set<String> extraPermissionCodes = dbPermissionCodes.stream()
                    .filter(code -> !defPermissionCodes.contains(code))
                    .collect(Collectors.toSet());
            if (!extraPermissionCodes.isEmpty()) {
                List<PermissionPo> extraPermissions = permissionDataService.listPermissionByCodes(extraPermissionCodes);
                extraPermissions.forEach(permission -> {
                    RolePermissionPo rp = dbPermissionMap.get(permission.getId());
                    if (Objects.nonNull(rp)) {
                        rp.setUpdateBy(1L);
                        rp.setDelete(Boolean.TRUE);
                        rolePermissionDataService.save(rp);
                    }
                });
            }
        });
    }
}
